#include <iostream>
#include <cstdio>
#include <ctime>
#include <string>
#include <sstream>
#include <chrono>
#include <atomic>
#include <random>
#include <iomanip>
#include "message.hpp"

#define LDBG 0
#define LINF 1
#define LERR 2

#define LDEFAULT LDBG

#define LOG(level, format, ...)                                                         \
    {                                                                                   \
        if (level >= LDEFAULT)                                                          \
        {                                                                               \
            time_t t = time(nullptr);                                                   \
            struct tm *lt = localtime(&t);                                              \
            char tmp[32] = {0};                                                         \
            strftime(tmp, 31, "%Y-%m-%d %T", lt);                                       \
            printf("[%s][%s:%d] " format "\n", tmp, __FILE__, __LINE__, ##__VA_ARGS__); \
        }                                                                               \
    }

#define DLOG(format, ...) LOG(LDBG, format, ##__VA_ARGS__);
#define ILOG(format, ...) LOG(LINF, format, ##__VA_ARGS__);
#define ELOG(format, ...) LOG(LERR, format, ##__VA_ARGS__);

std::string Uuid()
{
    std::stringstream ss;
    // 1.构造一个机器随机数对象
    std::random_device rd;
    // 2.以机器随机数为种子构造伪随机数对象
    std::mt19937 generator(rd());
    // 3.构造限定数据范围的对象
    std::uniform_int_distribution<int> distribution(0, 255);
    // 4.生成8个随机数，按照特定格式组织成为16进制数字字符的字符串
    for (int i = 0; i < 8; i++)
    {
        if (i == 4 || i == 6)
            ss << "-";
        ss << std::setw(2) << std::setfill('0') << std::hex << distribution(generator);
    }
    ss << "-";
    // 5.定义一个8字节序号，逐字节组织成为16进制数字字符的字符串
    static std::atomic<size_t> seq(1);
    size_t cur = seq.fetch_add(1);
    for (int i = 7; i >= 0; i--)
    {
        if (i == 5)
            ss << "-";
        ss << std::setw(2) << std::setfill('0') << std::hex << ((cur >> (i * 8)) & 0xFF);
    }

    return ss.str();
}

int main()
{
    // DLOG("nightcord");
    // for (int i = 0; i < 10; i++)
    // {
    //     std::string uuid = Uuid();
    //     std::cout << uuid << std::endl;
    // }

    NightCord::BaseMessage::ptr bmp = NightCord::MessageFactory::create(NightCord::MType::REQ_RPC);
    NightCord::RpcRequest::ptr rrp = NightCord::MessageFactory::create<NightCord::RpcRequest>();
    Json::Value val;3
    val["num1"] = "127";
    val["num2"] = "210";
    rrp->setMethod("knd");
    rrp->setParams(val);
    std::string str;
    str = rrp->serialize();
    std::cout << str << std::endl;

    // bool ret = bmp->unserialize(str);
    // NightCord::RpcRequest::ptr rrp2 = std::dynamic_pointer_cast<NightCord::RpcRequest>(bmp);
    // if (ret == false)
    //     return -1;
    // std::cout << rrp2->method() << std::endl;
    // std::cout << rrp2->params()["num1"].asString() << std::endl;
    // std::cout << rrp2->params()["num2"].asString() << std::endl;

    bool ret = rrp->unserialize(str);
    // NightCord::RpcRequest::ptr rrp2 = std::dynamic_pointer_cast<NightCord::RpcRequest>(bmp);
    if (ret == false)
        return -1;
    std::cout << rrp->method() << std::endl;
    std::cout << rrp->params()["num1"].asString() << std::endl;
    std::cout << rrp->params()["num2"].asString() << std::endl;
    return 0;
}